﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using Editor.WinForm.DocToolkit;
using System.Diagnostics;
using Editor.WinForm;
using Editor.SourceControl;
using System.Reflection;
using WeifenLuo.WinFormsUI.Docking;
using System.Threading;
using Editor.Log;
using CasaEngineEditor.Log;
using CasaEngine.SourceControl;
using CasaEngineWrapper;

namespace Editor
{
    public partial class MainForm 
        : Form
    {
        #region Fields

        private MruManager m_MruManager;
        private const string m_RegistryPath = "Software\\Studio_XC\\CasaEngineEditor";

        private ProjectConfigForm m_ProjectConfigForm = null;
        private LogForm m_LogForm = null;
        private RenderForm m_RenderForm = null;
        private SubMainForm m_SubMainForm = null;
        private Game m_Game;

        #endregion

        #region Properties

        #endregion

        #region Constructor

        /// <summary>
        /// 
        /// </summary>
        public MainForm()
        {
            InitializeComponent();

            m_LogForm = new LogForm();
            m_LogForm.Show(dockPanel1, DockState.DockBottom);

            m_RenderForm = new RenderForm();
            m_RenderForm.Show(dockPanel1, DockState.Document);

            //ExternalTool.SaveProject = saveToolStripMenuItem_Click;

            /*try
            {
                LogManager.Instance.AddLogger(new FileLogger(Environment.CurrentDirectory + "\\log-" + DateTime.Now.ToString("dd-MM-yy-HH-mm-ss") + ".txt"));
            }
            catch (Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Add Logger error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }*/

            SourceControlManager.Instance.Initialize(new P4SourceControl());
            EnableComponent(false);

            m_Game = new Game(m_RenderForm.RenderControl.Handle);

            Thread thread = new Thread(
                new ParameterizedThreadStart(delegate(object g) 
                    { 
                        ((Game)g).Run(); 
                    }));
            thread.Start(m_Game);

            m_MruManager = new MruManager();
            m_MruManager.Initialize(
                this,									// owner form
                toolStripMenuItemRecentProject,         // Recent Files menu item
                fileToolStripMenuItem,					// parent
                m_RegistryPath);						// Registry path to keep MRU list

            m_MruManager.MruOpenEvent += delegate(object sender_, MruFileOpenEventArgs e_)
            {
                LoadProject(e_.FileName);
            };

            SetTitle();

#if !UNITEST
            if (m_MruManager.GetFirstFileName != null)
            {
                //LoadProject(m_MruManager.GetFirstFileName);
            }
#endif
        }

        #endregion

        #region Methods

        #region Main Menu

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void newToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDialog = new SaveFileDialog();

            saveDialog.Title = "New Project";
            saveDialog.Filter = "Resources Files (*.xml)|*.xml|" +
                               "All Files (*.*)|*.*";

            if (saveDialog.ShowDialog(this) == DialogResult.OK)
            {
#if !DEBUG
                try
                {
#endif
                CreateProject(saveDialog.FileName);
                LogManager.Instance.WriteLine("New project successfully created");
#if !DEBUG
                }
                catch (Exception ex)
                {
                    LogManager.Instance.WriteException(ex);
                }
#endif
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileDialog form = new OpenFileDialog();

            form.Title = "Open Project";
            form.Filter = "Project Files (*.xml)|*.xml|" +
                               "All Files (*.*)|*.*";

            if (form.ShowDialog(this) == DialogResult.OK)
            {
#if !DEBUG
                try
#endif
                {
                    LoadProject(form.FileName);
                }
#if !DEBUG
                catch (Exception ex)
                {
                    LogManager.Instance.WriteException(ex);
                }
#endif
            }

            form.Dispose();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();

            /*if (string.IsNullOrEmpty(GameInfo.Instance.ProjectManager.ProjectFileOpened) == true)
            {
                saveAsToolStripMenuItem_Click(this, EventArgs.Empty);
            }
            else
            {
#if !DEBUG
                try
#endif
                {
                    SaveProject(GameInfo.Instance.ProjectManager.ProjectFileOpened);
                }
#if !DEBUG
                catch (Exception ex)
                {
                    LogManager.Instance.WriteException(ex);
                }
#endif
            }*/
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveFileDialog saveDialog = new SaveFileDialog();

            saveDialog.Title = "Save project";
            saveDialog.Filter = "Project Files (*.xml)|*.xml|" +
                               "All Files (*.*)|*.*";

            if (saveDialog.ShowDialog(this) == DialogResult.OK)
            {
                try
                {
                    SaveProject(saveDialog.FileName);
                }
                catch (Exception ex)
                {
                    LogManager.Instance.WriteException(ex);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItemCloseProject_Click(object sender, EventArgs e)
        {
            ClearProject();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckExternalTool()
        {
            //throw new NotImplementedException();
            /*this.pluginsToolStripMenuItem.DropDownItems.Clear();
            string[] names = GameInfo.Instance.ExternalToolManager.GetAllToolNames();
            int i = 0;

            foreach (string name in names)
            {
                ToolStripMenuItem toolStripItem = new ToolStripMenuItem();
                toolStripItem.Name = name;
                this.newToolStripMenuItem.Size = new System.Drawing.Size(152, 22);
                toolStripItem.Text = name;
                toolStripItem.Click += new System.EventHandler(this.OnExternalToolItem_Click);
                this.pluginsToolStripMenuItem.DropDownItems.Add(toolStripItem);
                i++;
            }*/
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnExternalToolItem_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();

#if !DEBUG
            try
            {
#endif
            ToolStripMenuItem item = (ToolStripMenuItem)sender;
            //GameInfo.Instance.ExternalToolManager.RunTool(this, item.Name);
#if !DEBUG
            }
            catch (Exception ex)
            {
                DebugHelper.ShowException(ex);
            }
#endif
        }

        /// <summary>
        /// 
        /// </summary>
        private void SetTitle()
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(asm.Location);

            this.Text = "Project Editor - " /*+ GameInfo.Instance.ProjectConfig.ProjectName*/ + " - " + fvi.ProductVersion;

#if DEBUG
            this.Text += " - DEBUG";
#endif
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buildAssetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();
            /*BuildAssetForm form = new BuildAssetForm();
            form.ShowDialog(this);
            form.Dispose();*/
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripMenuItemSourceControlOption_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();

            /*SourceControlConnectionForm form = new SourceControlConnectionForm();

            if (form.ShowDialog(this) == DialogResult.OK)
            {
                SourceControlManager.Instance.Server = form.Server;
                SourceControlManager.Instance.User = form.User;
                SourceControlManager.Instance.Workspace = form.Workspace;
                SourceControlManager.Instance.Password = form.Password;
                SourceControlManager.Instance.SaveConfig(GameInfo.Instance.ProjectManager.ProjectPath + Path.DirectorySeparatorChar + ProjectManager.ConfigDirPath);
                SourceControlManager.Instance.SourceControl.Connect();
            }*/
        }

        #region Debug

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void debugToolStripMenuItem_Click(object sender, EventArgs e)
        {
            debugToolStripMenuItem.Checked = true;
            normalToolStripMenuItem.Checked = false;
            noneToolStripMenuItem.Checked = false;
            LogManager.Instance.Verbosity = LogManager.LogVerbosity.Debug;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void infoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            normalToolStripMenuItem.Checked = true;
            debugToolStripMenuItem.Checked = false;
            noneToolStripMenuItem.Checked = false;
            LogManager.Instance.Verbosity = LogManager.LogVerbosity.Info;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void noneToolStripMenuItem_Click(object sender, EventArgs e)
        {
            noneToolStripMenuItem.Checked = true;
            debugToolStripMenuItem.Checked = false;
            normalToolStripMenuItem.Checked = false;
            LogManager.Instance.Verbosity = LogManager.LogVerbosity.None;
        }

        #endregion

        #endregion

        #region Project Methods

        /// <summary>
        /// 
        /// </summary>
        private void ClearProject()
        {
            /*SpriteSheetTaskListForm.Clear();
            GameInfo.Instance.ExternalToolManager.Clear();
            GameInfo.Instance.ProjectManager.Clear();*/
            EnableComponent(false);

            DisposeControl(m_ProjectConfigForm);
            DisposeControl(m_SubMainForm);
            //DisposeControl(m_LogForm);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="control_"></param>
        private void DisposeControl(Control control_)
        {
            if (control_ != null
                && control_.IsDisposed == false)
            {
                control_.Dispose();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName_"></param>
        private void CreateProject(string fileName_)
        {
            throw new NotImplementedException();

#if !DEBUG
            try
            {
#endif
            ClearProject();
            /*GameInfo.Instance.ProjectManager.CreateProject(fileName_);
            GameInfo.Instance.ProjectConfig.ProjectName = "New Project"; */
            OnProjectLoaded(fileName_);
#if !DEBUG
            }
            catch (System.Exception e)
            {
                
            }
#endif
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName_"></param>
        private void LoadProject(string fileName_)
        {
            //throw new NotImplementedException();

            
            if (File.Exists(fileName_) == false)
            {
                m_MruManager.Remove(fileName_);
                MessageBox.Show("The project file " + fileName_ + " doesn't exists!\n It will be remove from the recent files list.");
                return;
            }

#if !DEBUG
            try
            {
#endif
            ClearProject();            
            //GameInfo.Instance.ProjectManager.Load(fileName_);
            CheckExternalTool();
            /*SourceControlManager.Instance.LoadConfig(Path.GetDirectoryName(fileName_) + Path.DirectorySeparatorChar + ProjectManager.ConfigDirPath);

#if !UNITTEST
            SourceControlManager.Instance.SourceControl.Connect();
            
            if (SourceControlManager.Instance.SourceControl.IsValidConnection() == false)
            {
                //Ask connection information
                //SourceControlConnectionForm form = new SourceControlConnectionForm();

                //if (form.ShowDialog(this) == DialogResult.OK)
                //{
                //    SourceControlManager.Instance.Server = form.Server;
                //    SourceControlManager.Instance.User = form.User;
                //    SourceControlManager.Instance.Workspace = form.Workspace;
                //    SourceControlManager.Instance.Password = form.Password;
                //    SourceControlManager.Instance.SourceControl.Connect();

                //    if (SourceControlManager.Instance.SourceControl.IsValidConnection() == true)
                //    {
                //        SourceControlManager.Instance.CheckProjectFiles();
                //    }
                //}
            }
#endif
            */
            OnProjectLoaded(fileName_);
#if !DEBUG
            }
            catch (System.Exception ex)
            {
                LogManager.Instance.WriteException(ex);
            }
#endif
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="fileName_"></param>
        private new void SaveProject(string fileName_)
        {
            throw new NotImplementedException();

#if !DEBUG
            try
            {
#endif
            /*if (GameInfo.Instance.ProjectManager.Save(fileName_) == true)
            {
                LogManager.Instance.WriteLine("Project ",
                    "\GameInfo.Instance.ProjectConfig.ProjectName + "\"", System.Drawing.Color.Blue,
                    " successfully saved.");
            }
            else
            {
                LogManager.Instance.WriteLineError("Can't save the project.");
            }*/

#if !DEBUG
            }
            catch (System.Exception ex)
            {
                LogManager.Instance.WriteException(ex);
            }
#endif
        }

        /// <summary>
        /// 
        /// </summary>
        private void OnProjectLoaded(string fileName_)
        {
            //throw new NotImplementedException();

            EnableComponent(true);
            m_MruManager.Add(fileName_);
            SetTitle();
            /*LogManager.Instance.WriteLine("Project ",
                "\GameInfo.Instance.ProjectConfig.ProjectName + "\" ", System.Drawing.Color.Blue,
                "(", GameInfo.Instance.ProjectManager.ProjectFileOpened, ")", " successfully loaded.");*/
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="state_"></param>
        private void EnableComponent(bool state_)
        {
            buildAssetToolStripMenuItem.Enabled = state_;

            foreach (ToolStripItem item in toolStrip1.Items)
            {
                item.Enabled = state_;
            }
        }

        #endregion

        #region ToolStrip Menu

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonProjectConfig_Click(object sender, EventArgs e)
        {
            if (m_ProjectConfigForm == null
                || m_ProjectConfigForm.IsDisposed == true)
            {
#if !DEBUG
                try
                {
#endif
                m_ProjectConfigForm = new ProjectConfigForm();
#if !DEBUG
                }
                catch (Exception ex)
                {
                    DebugHelper.ShowException(ex);
                }
#endif
            }
            else
            {
                m_ProjectConfigForm.Focus();
                return;
            }

            if (m_ProjectConfigForm != null)
            {
                m_ProjectConfigForm.Show();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButtonWorldProperties_Click(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButtonActionGraph_Click(object sender, EventArgs e)
        {
            //ActionGraphForm f = new ActionGraphForm();
            //f.Show(dockPanel1, DockState.Document);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolStripButtonContentBrowser_Click(object sender, EventArgs e)
        {
            if (m_SubMainForm == null
                || m_SubMainForm.IsDisposed == true)
            {
                m_SubMainForm = new SubMainForm();
            }

            m_SubMainForm.Show();
        }

        #region Launch Game

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonLaunchGame_Click(object sender, EventArgs e)
        {
            LaunchGame();
        }

        /// <summary>
        /// 
        /// </summary>
        private void LaunchGame()
        {
            throw new NotImplementedException();

#if !DEBUG
            try
            { 
#endif
            /*saveToolStripMenuItem_Click(this, EventArgs.Empty);

            BgWorkerForm form = new BgWorkerForm(BuildAssetFileInContentFolder);
            //BgWorkerForm form = new BgWorkerForm(CopyAssetFileInContentFolder);
            form.Text = "Copying ressource files";
            form.ShowDialog(this);

            bool res = form.Result == null ? false :
                form.Result.Error != null ? false :
                form.Result.Result is bool ? (bool)form.Result.Result : false;

            if (res == false)
            {
                if (form.Result != null) //else : user cancel the operation : no message
                {
                    if (form.Result.Error != null)
                    {
                        LogManager.Instance.WriteException(form.Result.Error);
                        MessageBox.Show(this, form.Result.Error.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    else
                    {
                        LogManager.Instance.WriteLineError("Can't copy ressource files : unknown error!");
                        MessageBox.Show(this, "Can't copy ressource files : unknown error!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }

                return;
            }

            form.Dispose();

            ProcessStartInfo myInfo = new ProcessStartInfo();
            myInfo.FileName = FindGameExe();

            if (string.IsNullOrWhiteSpace(myInfo.FileName) == false)
            {
                myInfo.WorkingDirectory = Path.GetDirectoryName(myInfo.FileName);
                myInfo.Arguments = Path.GetFileName(GameInfo.Instance.ProjectManager.ProjectFileOpened);
                Process.Start(myInfo);
            }
            else
            {
                LogManager.Instance.WriteLineError("Game exe not found!");
                MessageBox.Show(this, "Game exe not found!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }*/
#if !DEBUG
            }
            catch (Exception ex)
            {
                DebugHelper.ShowException(ex);
            }
#endif
        }

        /// <summary>
        /// 
        /// </summary>
        /*private void CopyAssetFileInContentFolder(object sender, DoWorkEventArgs e)
        {
            FileInfo fi, fi2;
            bool ro;
            string destFile;

            string[] xnbs = Directory.GetFiles(GameInfo.Instance.ProjectManager.ProjectPath + Path.DirectorySeparatorChar + ProjectManager.XNBDirPath, "*.xnb");

            int percent = 0;
            BackgroundWorker bg = sender as BackgroundWorker;

            string destPath = GameInfo.Instance.ProjectManager.ProjectPath + Path.DirectorySeparatorChar + ProjectManager.GameDirPath + "\\Content\\";

            List<string> readOnlyFiles = new List<string>();

            foreach (string file in xnbs)
            {
                percent++;
                bg.ReportProgress(
                    (int)(((float)percent / (float)(xnbs.Length + 1)) * 100.0f),
                    "copying " + Path.GetFileName(file) + " ... (" + percent + "/" + (xnbs.Length + 1) + ")");

                fi = new FileInfo(file);
                ro = fi.IsReadOnly;
                destFile = destPath + Path.GetFileName(file);

                fi.IsReadOnly = false; //source control can put the file in readonly mode

                //avoid erase readonly file
                if (File.Exists(destFile) == true)
                {
                    fi2 = new FileInfo(destFile);
                    fi2.IsReadOnly = false;
                    fi2.Delete();
                }

                File.Copy(file, destFile, true);
                fi.IsReadOnly = ro;
            }

            //project File
            destFile = GameInfo.Instance.ProjectManager.ProjectPath + Path.DirectorySeparatorChar + ProjectManager.GameDirPath + "\\Content\\" + Path.GetFileName(GameInfo.Instance.ProjectManager.ProjectFileOpened);
            fi = new FileInfo(GameInfo.Instance.ProjectManager.ProjectFileOpened);
            ro = fi.IsReadOnly;
            fi.IsReadOnly = false;

            fi2 = new FileInfo(destFile);
            if (fi2.Exists == true)
            {
                fi2.IsReadOnly = false;
                fi2.Delete();
            }

            File.Copy(GameInfo.Instance.ProjectManager.ProjectFileOpened,
                destFile,
                true);

            fi.IsReadOnly = ro;

            //percent++;
            //bg.ReportProgress(
            //    (int)(((float)percent / (float)(xnbs.Length + 1)) * 100.0f),
            //    "copying files ... (" + percent + "/" + (xnbs.Length + 1) + ")");

            e.Result = true;
        }*/

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BuildAssetFileInContentFolder(object sender, DoWorkEventArgs e)
        {
            throw new NotImplementedException();

            /*FileInfo fi, fi2;
            bool ro;
            string destFile;

            int percent = 0;
            BackgroundWorker bg = sender as BackgroundWorker;

            string xnbPath = GameInfo.Instance.ProjectManager.ProjectPath + Path.DirectorySeparatorChar + ProjectManager.GameDirPath + "\\Content\\";

            // AssetBuildParam doit implementer IObservable
            // pour modifier BuildParamChanged
            
            foreach (AssetInfo info in GameInfo.Instance.AssetManager.Assets)
            {
                bg.ReportProgress(
                    (int)(((float)percent / (float)(GameInfo.Instance.AssetManager.Assets.Length + 1)) * 100.0f),
                    "building " + info.Name + " ... (" + percent + "/" + (GameInfo.Instance.AssetManager.Assets.Length + 1) + ")");

                fi = new FileInfo(info.FileName);
                if (File.Exists(xnbPath + info.Name + ".xnb") == false
                    || GameInfo.Instance.AssetManager.AssetNeedToBeRebuild(info) == true)
                {
                    GameInfo.Instance.AssetManager.RebuildAsset(info);
                }

                percent++;
            }

            GameInfo.Instance.AssetManager.SaveAssetBuildInfo();

            //project File
            destFile = GameInfo.Instance.ProjectManager.ProjectPath + Path.DirectorySeparatorChar + ProjectManager.GameDirPath + "\\Content\\" + Path.GetFileName(GameInfo.Instance.ProjectManager.ProjectFileOpened);
            fi = new FileInfo(GameInfo.Instance.ProjectManager.ProjectFileOpened);
            ro = fi.IsReadOnly;
            fi.IsReadOnly = false;

            fi2 = new FileInfo(destFile);
            if (fi2.Exists == true)
            {
                fi2.IsReadOnly = false;
                fi2.Delete();
            }

            File.Copy(GameInfo.Instance.ProjectManager.ProjectFileOpened,
                destFile,
                true);

            fi.IsReadOnly = ro;

            //percent++;
            //bg.ReportProgress(
            //    (int)(((float)percent / (float)(xnbs.Length + 1)) * 100.0f),
            //    "copying files ... (" + percent + "/" + (xnbs.Length + 1) + ")");

            e.Result = true;*/
        }

        /// <summary>
        /// 
        /// </summary>
        private string FindGameExe()
        {
            throw new NotImplementedException();
            /*
            string[] exes = Directory.GetFiles(GameInfo.Instance.ProjectManager.ProjectPath + Path.DirectorySeparatorChar + ProjectManager.GameDirPath, "*.exe");

            if (exes.Length > 0)
            {
                return exes[0];
            }

            return string.Empty;
             * */
        }

        #endregion

        #region Event

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            m_Game.Exit();
            Dispose(true);
        }

        #endregion

        #endregion

        #endregion       
    }
}
